<?php

namespace Plugin\AdCloak\Middleware\Shop;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Matrix\Exception;
use Plugin\AdCloak\Models\AdCloakUrls;
use function Symfony\Component\Console\Debug\getClientIp;

const cookiesKey = "http_site_tag_cloak";

class CloakRequired
{


    /**
     * Handle an incoming request.
     *
     * @param Request $request
     * @param Closure $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next): mixed
    {
        if ($request->isMethod('get')) {
            $path = isset($_SERVER['REDIRECT_URL']) ? $_SERVER['REDIRECT_URL'] : '';
            if (substr($path, 0, 5) != admin_name()) {
                if (self::remoteClient($request)) {//来自自己的请求
                    return $next($request);
                }
                self::checkUrlIsUser();
                $ip = self::remoteClient($request, 'ip');
                if ($ip != $_SERVER['SERVER_ADDR'] || (isset($_GET['test']) && ($_GET['test'] == '123'))) {//不是本机的请求才要进来执行
                    if (self::checkAllUrlRedirect()) {//全部都转代理
                        $content  = self::goUrl();
                        $response = $next($request);
                        $response->setContent($content);
                        return $response;
                    } else {

                        $plugin     = plugin_setting("ad_cloak");
                        $cache_type = isset($plugin['cache']) ? $plugin['cache'] : 1;

                        if ($cache_type == 1 && isset($_COOKIE[cookiesKey])) {
                            $tag = $_COOKIE[cookiesKey];
                            if ($tag != 'user') {//非普通用户请求
                                $content  = self::goUrl();
                                $response = $next($request);
                                $response->setContent($content);
                                return $response;
                            }
                        } else {
                            if (self::checkUrlIsUser()) {//真人

                            } else {
                                $content  = self::goUrl();
                                $response = $next($request);
                                $response->setContent($content);
                                return $response;
                            }
                        }
                    }
                } else {

                }
            }
        }
        return $next($request);
    }

    private static function remoteClient($request, $type = 'check_self')
    {
        if ($type == 'check_self') {
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $HTTP_X_FORWARDED_FOR = $_SERVER['HTTP_X_FORWARDED_FOR'];
                $HTTP_X_FORWARDED_FOR = explode(",", $HTTP_X_FORWARDED_FOR);
                foreach ($HTTP_X_FORWARDED_FOR as $for_ip) {
                    $for_ip = trim($for_ip);
                    if ($for_ip == '0.0.0.1') {//来自自己的请求
                        return true;
                    }
                }
            }
            return false;
        } else {
            $ip = null;
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $HTTP_X_FORWARDED_FOR = $_SERVER['HTTP_X_FORWARDED_FOR'];
                $HTTP_X_FORWARDED_FOR = explode(",", $HTTP_X_FORWARDED_FOR);
                foreach ($HTTP_X_FORWARDED_FOR as $for_ip) {
                    $for_ip = trim($for_ip);
                    if ($for_ip != '0.0.0.1') {
                        $ip = $for_ip;
                        break;
                    }
                }
            }
            if (empty($ip)) {
                $ip = $request->getClientIp();
            }
            if (empty($ip)) {
                $ip = $_SERVER['REMOTE_ADDR'];
            }
            return $ip;
        }
    }

    //检测是否为全部链接都代理掉
    private static function checkAllUrlRedirect()
    {
        $key = "ad_cloak_all_reirect_status";

        $plugin             = plugin_setting("ad_cloak");
        $cache_type         = isset($plugin['cache']) ? $plugin['cache'] : 1;
        $cloak_all_redirect = null;
        if ($cache_type == 1) {
            $cloak_all_redirect = Cache::get($key);
        }
        if ($cloak_all_redirect == false) {
            $plugin             = plugin_setting("ad_cloak");
            $cloak_all_redirect = isset($plugin['all_redirect']) ? $plugin['all_redirect'] : 0;
            Cache::put($key, $cloak_all_redirect, Carbon::now()->addMinute());//缓存1分钟
        }

        if ($cloak_all_redirect == '1') {
            return true;
        }
        return false;
    }


    //检测是否为真人
    private static function checkUrlIsUser()
    {
        $request = Request::capture();
        if ($request->path() == '/') {
            $host = $request->url() . "/";
        } else {
            $hosts = explode($request->path(), $request->url());
            $host  = $hosts[0];
        }

        $host = str_replace("https://", "", $host);
        $host = str_replace("http://", "", $host);
        $host = str_replace("/", "", $host);
        //$ip     = $request->getClientIp();

        $ip     = self::remoteClient($request, 'ip');
        $domain = $host;
        $ua     = $request->userAgent();
        $rs     = self::checkClient($ip, $domain, $ua, $request->referer);

        if ($rs == 1) {//正常可以走的
            setcookie(cookiesKey, "user");
            return true;
        } else if ($rs == 2) {//查询异常的情况，下次还要接着查
            return false;
        }
        //确定是要拦截的
        setcookie(cookiesKey, "other");
        return false;
    }

    //输出对应页面数据
    private static function goUrl()
    {
        $request = Request::capture();
        $url     = $request->url();
        $urls    = explode("?", $url);
        $urlFrom = $urls[0];
        $key     = md5($urlFrom);

        $plugin     = plugin_setting("ad_cloak");
        $cache_type = isset($plugin['cache']) ? $plugin['cache'] : 1;


        $to    = null;
        $toUrl = null;
        if ($cache_type == 1) {
            $toUrl = Cache::get($key);
        }
        if (empty($toUrl)) {
            $toUrl = self::getToUrl($urlFrom);
        }
        if (empty($toUrl)) {
            die("链接错误");
        }
        //print_r(substr($toUrl,0, 4));exit;
        if (substr($toUrl, 0, 4) != 'http') {
            echo $toUrl;
            exit;
        }
        return self::curlSite($toUrl);
    }


//代理请求
    private static function curlSite($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        //加入自己访问的特征
        $headers = [
            'X-Forwarded-For: 0.0.0.1'
        ];
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        $result = curl_exec($ch);
        curl_close($ch);
// 输出返回的结果
        return $result;
    }

    private static function checkClient($ip, $domain, $ua, $referer)
    {
        $plugin           = plugin_setting("ad_cloak");
        $do_redirect_type = isset($plugin['do_redirect_type']) ? $plugin['do_redirect_type'] : 1;


        //检测是否有匹配到拦截的ip
        $ips = isset($plugin['ips']) ? $plugin['ips'] : [];
        if (!empty($ips)) {
            try {
                $ips = explode(",", $ips);
                if (in_array($ip, $ips)) {//要拦截
                    return 0;
                }
            } catch (\Exception $exception) {
                throw new Exception("IP地址池格式不正确");
            }
        }
        if ($do_redirect_type == 1) {
            $rs = self::posturl('https://cloakplus.com/v4/', [
                'username' => $plugin['username'],
                'password' => $plugin['password'],
            ], [
                'ip'      => $ip,
                'domain'  => $domain,
                'ua'      => $ua,
                'referer' => $referer,
                'country' => $plugin['country'],
                'mode'    => $plugin['mode'],
                'mobile'  => $plugin['mobile'],
            ], 30);
            try {
                if ($rs == 'Authorization Required') {
                    die('cloakplus 账号或密码不对');
                }
                $rs2 = json_decode($rs, true);
                if ($rs2['result']) {//正常可用的ip
                    return 1;
                }
                return 0;
            } catch (Exception $exception) {
                throw new Exception("cloakplus查询异常");
                return 2;
            }
        } else if ($do_redirect_type == 3) {//使用ipinfo

            return 1;

            if (!isset($plugin['ipinfo_org']) || empty($plugin['ipinfo_org'])) {
                return 1;
            }
            if (!isset($plugin['ipinfo_token']) || empty($plugin['ipinfo_token'])) {
                return 1;
            }
            $token = $plugin['ipinfo_token'];
            $rs    = self::httpGet('https://ipinfo.io/' . $ip . '/json?token=' . $token);
            try {
                $rs = json_decode($rs, true);
            } catch (Exception $exception) {
                throw new Exception("ipinfo查询异常");
                return 2;
            }
            $org         = strtolower($rs['org']);
            $ipinfo_orgs = explode(",", $plugin['ipinfo_org']);
            foreach ($ipinfo_orgs as $ipinfo_org) {
                $position = strpos($org, strtolower($ipinfo_org));
                if ($position !== false) {
                    return 0;
                } else {
                }
            }
            return 1;
        } else {//
            return 1;
        }
    }

    private static function httpGet($url)
    {
        try {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 不直接输出，返回到变量
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); // 连接超时（秒）
            curl_setopt($ch, CURLOPT_TIMEOUT, 60); // 执行超时（秒）

            curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)");
            // curl_setopt($ch, CURLOPT_POSTFIELDS, $sendInfo);
            // curl_setopt($ch, CURLOPT_INTERFACE, request()->getClientIp()); // 设置IP地址
            $headers   = [];
            $headers[] = 'Content-Type: application/json';

            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 信任任何证书
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 检查证书中是否设置域名
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

            $curl_result = curl_exec($ch);
            curl_close($ch);
            return $curl_result;
        } catch (Exception $e) {
            return null;
        }
    }

    public static function posturl($url, $users, $post = [])
    {
        $httppost = http_build_query($post);
        $SSL      = substr($url, 0, 8) == "https://" ? true : false;
        $ch       = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        if ($SSL) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 信任任何证书
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 检查证书中是否设置域名
        }

        //curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36');
        curl_setopt($ch, CURLOPT_HEADER, false);
        // curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_ENCODING, 'utf8');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        if (!empty($post)) {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $httppost);
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: Basic ' . base64_encode($users['username'] . ':' . $users['password'])
        ]);

        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
        //Log::debug($post);
        //Log::debug(base64_encode($users['username'] . ':' . $users['password']));
        // curl_setopt($ch, CURLOPT_COOKIE, $cookies);
        $result = curl_exec($ch);
        //Log::debug($result);
        $err = curl_error($ch);
        //Log::debug($err);
        curl_close($ch);
        return $result;
    }

    private static function getToUrl($urlFrom)
    {
        $to = AdCloakUrls::query()->where("url_from", 'like', $urlFrom . '%')->orderByDesc('sort')->first();
        if (empty($to)) {
            $plugin     = plugin_setting("ad_cloak");
            $cache_type = isset($plugin['cache']) ? $plugin['cache'] : 1;

            $key2  = md5('cloak_default_url');
            $toUrl = null;
            if ($cache_type == 1) {
                $toUrl = Cache::get($key2);
            }
            if (empty($toUrl)) {
                $to = AdCloakUrls::query()->where("type", 1)->orderByDesc('sort')->first();
                if (!empty($to)) {
                    $toUrl = $to->url_to;
                    Cache::put($key2, $toUrl, \Carbon\Carbon::now()->addMinute());//缓存1分钟
                }
            }
        } else {
            $toUrl = $to->url_to;
        }
        return $toUrl;
    }
}
